struts-java web后台知识简单总结
struts1 所学版本:1.3.8
struts2 所学版本:2.5.10.1
补充 tomcat 知识
默认虚拟主机
我们知道,server.xml 中可以配置多个 host,在 engine 标签中可以修改 default 属性,即浏览器直接访问 ip 地址时,访问的哪一个虚拟主机。
默认 web application
一个虚拟主机中可以部署多个 web 应用。当浏览器指定了虚拟主机(或者 tomcat 知道了需要访问哪一个主机),没有指定 web 应用时,tomcat 会看 server.xml 中 host 标签,或者 $CATALINA_HOME/conf /Catalina/localhost 目录下有没有 context 标签的 path 属性设置为空,有的话,访问这个 web 应用。没有的话,访问 Tomcat/webapps/ROOT 应用(新下载的 tomcat 就是这种方式)。再没有的话,就报错。
默认主页
一个 web 应用中可以有很多个页面,当浏览器指定了 web 应用(或者 tomcat 知道了需要访问哪一个 web 应用),没有指定页面时,会有两种情况,自己不太确定会发生哪一种。凭感觉第二种更可能。
- tomcat 会访问 web.xml 中匹配了所有路径的 servlet。若没有这个 servlet,或者 这个 servlet 没有指定返回的页面时,就会访问欢迎页面。欢迎页面说明见下面。
- tomcat 会直接指定为欢迎页面,页面确定后,就是正常的处理流程了。如果没有欢迎页面,则访问 web.xml 中匹配了所有路径的 servlet。
经过自己测试,发现是第二种。
web.xml 中欢迎页面
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index1.jsp</welcome-file>
</welcome-file-list>
上面的例子指定了2个欢迎页面,显示时按顺序从第一个找起,如果第一个存在,就显示第一个,后面的不起作用。如果第一个不存在,就找第二个,以此类推。
关于欢迎页面:访问一个网站时,默认看到的第一个页面就叫欢迎页,一般情况下是由首页来充当欢迎页的。一般情况下,我们会在web.xml中指定欢迎页。但web.xml并不是一个Web的必要文件,没有web.xml,网站仍然是可以正常工作的。只不过网站的功能复杂起来后,web.xml的确有非常大用处,所以,默认创建的动态web工程在WEB-INF文件夹下面都有一个web.xml文件。
对于tomcat来说,当你只指定一个web的根名,没有指定具体页面,去访问时一个web时,如果web.xml文件中配置了欢迎页,那么就返回指定的那个页面作为欢迎页,而在文中没有web.xml文件,或虽然有web.xml,但web.xml也没指定欢迎页的情况下,它默认先查找index.html文件,如果找到了,就把index.html作为欢迎页还回给浏览器。如果没找到index.html,tomcat就去找index.jsp。找到index.jsp就把它作为欢迎页面返回。而如果index.html和index.jsp都没找到,又没有用web.xml文件指定欢迎页面,那此时tomcat就不知道该返回哪个文件了,它就显示The requested resource (/XXX) is not available(我就出现过这个问题)的页面。其中XXX表示web的根名。但如果你指定了具体页面,是可以正常访问的。
因为 tomcat/conf/web.xml 中有如下内容:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
参考网页:http://www.cnblogs.com/hxsyl/p/3435412.html
results 标签
default results type
<result-types>
<result-type name="dispatcher" default="true"
class="org.apache.struts2.dispatcher.ServletDispatcherResult" />
</result-types>
If a type attribute is not specified, the framework will use the default dispatcher type, which forwards to another web resource. If the resource is a JavaServer Page, then the container will render it, using its JSP engine.
Result element without defaults
<result name="success" type="dispatcher">
<param name="location">/ThankYou.jsp</param>
</result>
或者
<result>/ThankYou.jsp</result>
Tips:results 标签必须设置三个值:name,type,location。name 默认为“success”,type 默认为“dispatcher”。
struts2
struts.xml
package 标签作用:用来解决 package 中 action 重名的情况。
package提供了将多个Action组织为一个模块的方式。
package的名字必须是唯一的 package可以扩展,当一个package扩展自另一个package时该package会在本身配置的基础上加入扩展的package
的配置,父package必须在子package前配置。
abstract:设置package的属性为抽象的,抽象的package不能定义action。
官网标签说明:https://struts.apache.org/docs/package-configuration.html
namespace
namespace决定了action的访问路径,默认为””,可以接收所有路径的action。
namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action,
/xxx/index.action,或者/xxx/yyy/index.action.
namespace 最好也用模块来进行命名。
namespace 默认值为空字符串(“”)时,处理其他 package 中同名 action 处理不了的请求。即没有更精确 namespace 匹配时,用这个action。
Action
具体视图的返回可以由用户自己定义的Action来决定。
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容。
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可。
或者实现Action接口。
不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法。
当 action 标签中不配置 class 属性时,默认为 ActionSupport 类。
action 标签中 result 子标签默认 name=“result”。
路径问题
struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。
解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)。
或者指定basePath。
DMI
The default entry method to the handler class is defined by the Action interface.
Sometimes, developers like to create more than one entry point to an Action. A different entry point can be specified by the method attribute.
Action执行的时候并不一定要执行execute方法。
可以在配置文件中配置Action的时候用method=来指定执行哪个方法,也可以在url地址中动态指定(动态方法调用DMI)(推荐)。
前者会产生太多的action,所以不推荐使用。
action 的通配符匹配
<action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">
<result>/Student{1}_success.jsp</result>
</action>
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
<result>/{1}_{2}_success.jsp</result>
<!-- {0}_success.jsp -->
</action>
使用通配符,将配置量降到最低。
不过,一定要遵守”约定优于配置”的原则。
action 的属性接受参数
- 用 Action 的属性接受参数,通过请求的 url 传递给 action。
例子:/actionName!methodName?attributeName=attributeValue - 用 DomainModel 接受参数,也是通过请求的 url 传递给 action。
例子:/actionName!methodName?modelName.attributeName=attributeValue
当参数个数不匹配时,可以用 DTO 技术。(最常用) - 用 ModelDriven 传输参数,不常用。action 需要实现 ModelDriven 接口,请求的 url 与第一种一样。
获得 web 元素
action 中获得 Request,Session,Application 对象
方法一:
Map request = (Map) ActionContext.getContetx().get("request");
方法二:
action 实现 RequestAware,SessionAware,ApplicationAware 接口。
通过 DI(依赖注入)、IoC(控制反转)获得 request,session,application 对象。(只用这种)
action 中获得 HttpServletRequest,HttpSession,ServletContext 对象
方法一:(基本不用)
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
ServletContext application = session.getServletContext();
方法二:
action 实现 ServletRequestAware 接口。
也是通过依赖注入获得对象。
jsp 页面中获得 web 元素
<s:property value="#request.r1"/> | <%=request.getAttribute("r1") %>
附上 struts2 架构图
struts1 与 struts2 区别
struts1
- 基于Servlet(ActionServlet),actionForm众多(类的爆炸),action单例(数据安全[线程安全]问题).
- 将所有任务的解决都集于一身.(不容易扩展和定制)
- action位于控制层. extends Action{…}
- action更struts1的action和原生servlet api(HttpServletRequest,HttpServlerResponse)绑定在一起,因此不容易测试,需要部署到web容器中进行测试.
|
|
或者
|
|
<action-mappings>
<action path="/customerAction"
name="customerForm"
scope="request|session"
validate="true"
input="/xxx.jsp"
forward="/xxx.jsp"
type="xxxx..CustomerAction"
parameter="method">
</action>
</action-mappings>
访问方式:http://xxx/sss/customerAction.do?method=save,其中 method=save 表示传递了 method 参数,值为 save。
可以在 action 标签的forward 属性中设置,action产生的结果 forward 到哪一个 jsp。也可以在 action 对象返回的 ActionForward 对象中指定。
action execute 方法
数据的传递
可以把消息存放在 request 域中,jsp 文件通过 EL 表达式获取 。
request.setAttribute("message", "注册成功!!");
jsp 文件中内容:
${message}
forward 到哪一个 jsp
可以在 action返回的 ActionForward 对象中指定 forward 到哪一个 jsp:
return new ActionForward("/message.jsp");
也可以在 action 标签的forward 属性中设置 forward 到哪一个 jsp 后,
<forward name="message" path="/message.jsp"></forward>
代码中可以直接写:
return mapping.findForward("message");//会找到配置文件中 name="message" 的 forward 标签。
struts2
- 基于filter,没有actionform,action(原型的,独占).
- seperate aware:分离关注.解耦.(interceptor,拦截器).
- action是模型层(接受参数+pojo).
- action不需要和struts的action和原生servlet API(HttpServletRequest,HttpServlerResponse)耦合在一起.所以更容易测试,不需要一定要部署到web环境中进行测试.
struts2是更加整洁的mvc框架(原因是采用了seperate aware技术,实现任务的拆解).
/xxx.jsp
可以直接在配置文件中 result 标签中设置,action产生的结果 forward 到哪一个 jsp。
jsp 中可以使用 <s:property> 标签获得 value stack 中内容。
顺带也说一下不用框架,直接访问 servlet 对象情况
在 web.xml 文件中配置如下:
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>cn.itcast.FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/xxx</url-pattern>
</servlet-mapping>
tomcet 根据 url-pattern 来找到对应的 servlet-class 来相应请求。
产生的结果可以直接输出,也可以 forward 到 jsp。
request.getRequestDispatcher("/xxx.jsp").forward(request, response);